﻿using System;
using System.Linq;
using System.Threading.Tasks;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Shapes;
using com.IronOne.BoardPACWinAppBO.General;
using com.IronOne.BoardPACWinAppBO.Sync;
using com.IronOne.BoardPACWinAppService.Meeting;
using com.IronOne.BoardPACWinAppUtil.Enums;
using com.IronOne.BoardPACWinAppUtil.Util;
using GalaSoft.MvvmLight.Messaging;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace com.IronOne.BoardPACWinApp.View.UserControl
{
    public sealed partial class CalenderUserControl
    {
        //NOTE: https://winstoreappcalendar.codeplex.com/downloads/get/691256
        private IMeetingService _meetingService;

        public CalenderUserControl()
        {
            InitializeComponent();
            CurrentDate = DateTime.Today;
            SelectedDate = CurrentDate;

            Messenger.Default.Register<NotificationMessage<MessageDataModel>>(this, HandleMessages);
            _meetingService = new MeetingService();
        }

        public DateTime CurrentDate { get; set; }
        public DateTime SelectedDate { get; set; }
        private event EventHandler<TappedRoutedEventArgs> _selectionChange;

        public event EventHandler<TappedRoutedEventArgs> SelectionChange
        {
            add { _selectionChange += value; }
            remove { _selectionChange -= value; }
        }

        private async void HandleMessages(NotificationMessage<MessageDataModel> mdm)
        {
            try
            {
                if (!mdm.Notification.Equals(MessageCodes.SYNC_UPDATED_DATA)) return;
                var sudm = (SyncUpdatedDataModel) mdm.Content.MessageData;
                if (sudm.Meetings != null && sudm.Meetings.Count > 0)
                {
                    await
                        CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
                            async () =>
                            {
                                // Your UI update code goes here!
                                await InitializeCalendar();
                            });
                }
            }
            catch (Exception)
            {
            }
        }

        public void OnSelectionChange(object sender, TappedRoutedEventArgs e)
        {
            if (_selectionChange != null)
                _selectionChange(sender, e);
        }

        private async void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            await InitializeCalendar();
        }

        private async Task InitializeCalendar()
        {
            try
            {
                //Clear the grid whenever the user load the first time or change the date
                CalendarGrid.RowDefinitions.Clear();
                CalendarGrid.Children.Clear();

                //InitializeHeader();
                InitializeDayLabelBoxes();
                InitializePreviousMonthBoxes();
                await InitializeCurrentMonthBoxes();
                InitializeNextMonthBoxes();
            }
            catch (Exception)
            {
            }
        }

        private void InitializeDayLabelBoxes()
        {
            try
            {
                var column = 0;
                CalendarGrid.RowDefinitions.Add(new RowDefinition {Height = GridLength.Auto});
                foreach (var day in Enum.GetValues(typeof (DayOfWeek)))
                {
                    //Runtime generate controls and setting style
                    var box = new Rectangle {Style = Application.Current.Resources["CalendarLabelBox"] as Style};
                    box.SetValue(Grid.RowProperty, 0);
                    box.SetValue(Grid.ColumnProperty, column);

                    var textBlock = new TextBlock
                    {
                        Style = Application.Current.Resources["CalendarLabel"] as Style,
                        Text = day.ToString().Substring(0, 3).ToUpper()
                    };

                    //Runtime setting the control Grid.Row and Grid.Column XAML property value
                    textBlock.SetValue(Grid.RowProperty, 0);
                    textBlock.SetValue(Grid.ColumnProperty, column);

                    //Adding the box and the textblock control to the Grid during runtime
                    CalendarGrid.Children.Add(box);
                    CalendarGrid.Children.Add(textBlock);

                    column++;
                }
            }
            catch (Exception)
            {
            }
        }

        private void InitializePreviousMonthBoxes()
        {
            try
            {
                var previousMonthDate = CurrentDate.AddMonths(-1);
                var previousMonthDateIteration = new DateTime(previousMonthDate.Year, previousMonthDate.Month,
                    DateTime.DaysInMonth(previousMonthDate.Year, previousMonthDate.Month));
                CalendarGrid.RowDefinitions.Add(new RowDefinition {Height = new GridLength(1, GridUnitType.Star)});

                for (var dayOfWeek = (int) previousMonthDateIteration.DayOfWeek; dayOfWeek >= 0; dayOfWeek--)
                {
                    var item = new CalendarItemUserControl(previousMonthDateIteration, "",
                        Application.Current.Resources["CalendarOtherMonthItemBox"] as Style);
                    /*item.PointerEntered += (sender, args) =>
                    {
                        ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarMouseOverItemBox"] as Style;
                    };

                    item.PointerExited += (sender, args) =>
                    {
                        if (((CalendarItemUserControl)sender).Value == this.SelectedDate)
                            ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarSelectedItemBox"] as Style;
                        else
                            ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarOtherMonthItemBox"] as Style;
                    };*/

                    //delegate the tapped event to selection change event
                    /*item.Tapped += (sender, args) =>
                    {
                        //update the selected date value
                        this.SelectedDate = ((CalendarItemUserControl)sender).Value;
                        this.CurrentDate = this.CurrentDate.AddMonths(-1);
                        InitializeCalendar();

                        OnSelectionChange(sender, args);
                    };*/

                    item.SetValue(Grid.RowProperty, 1);
                    item.SetValue(Grid.ColumnProperty, dayOfWeek);

                    CalendarGrid.Children.Add(item);

                    previousMonthDateIteration = previousMonthDateIteration.AddDays(-1);
                }
            }
            catch (Exception)
            {
            }
        }

        private async Task InitializeCurrentMonthBoxes()
        {
            try
            {
                var meetingsByDate = await _meetingService.GetMeetingsByMonth(MonthSelection.ThisMonthOnly);
                var daysList = meetingsByDate.Select(x => x.Day).ToList();

                var row = 1;
                var maxDay = DateTime.DaysInMonth(CurrentDate.Year, CurrentDate.Month);
                for (var day = 1; day <= maxDay; day++)
                {
                    var dateIteration = new DateTime(CurrentDate.Year, CurrentDate.Month, day);
                    var dayOfWeek = (int) dateIteration.DayOfWeek;
                    CalendarItemUserControl item;

                    if (daysList.Contains(day))
                    {
                        item = new CalendarItemUserControl(dateIteration, day.ToString(),
                            Application.Current.Resources["CalendarMeetingDaysItemBox"] as Style);
                    }
                    else
                    {
                        item = new CalendarItemUserControl(dateIteration, day.ToString(),
                            Application.Current.Resources["CalendarItemBox"] as Style);
                    }

                    /*item.PointerEntered += (sender, args) => 
                    {
                        ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarMouseOverItemBox"] as Style; 
                    };

                    item.PointerExited += (sender, args) => 
                    {
                        if (((CalendarItemUserControl)sender).Value == this.SelectedDate)
                            ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarSelectedItemBox"] as Style; 
                        else
                            ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarItemUserControlBox"] as Style; 
                    };*/

                    //delegate the tapped event to selection change event
                    /*item.Tapped += (sender, args) =>
                    {
                        //get the box day value
                        ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarSelectedItemBox"] as Style;

                        //get the box before selected value and reset the color
                        var selectedItem = (CalendarItemUserControl)CalendarGrid.Children.Single(x =>
                                                x.GetType() == typeof(CalendarItemUserControl) &&
                                                ((CalendarItemUserControl)x).Value == this.SelectedDate);

                        selectedItem.GridStyle = Application.Current.Resources["CalendarItemUserControlBox"] as Style;

                        //update the selected date value
                        this.SelectedDate = ((CalendarItemUserControl)sender).Value;

                        OnSelectionChange(sender, args);
                    };*/

                    //highlight selected date
                    if (SelectedDate.CompareTo(dateIteration) == 0)
                        item.GridStyle = Application.Current.Resources["CalendarSelectedItemBox"] as Style;

                    item.SetValue(Grid.RowProperty, row);
                    item.SetValue(Grid.ColumnProperty, dayOfWeek);

                    CalendarGrid.Children.Add(item);

                    if (dayOfWeek != 6 || day == maxDay) continue;
                    row++;
                    CalendarGrid.RowDefinitions.Add(new RowDefinition
                    {
                        Height = new GridLength(1, GridUnitType.Star)
                    });
                }
            }
            catch (Exception)
            {
            }
        }

        private void InitializeNextMonthBoxes()
        {
            try
            {
                var nextMonthDate = CurrentDate.AddMonths(1);
                var nextMonthDateIteration = new DateTime(nextMonthDate.Year, nextMonthDate.Month, 1);

                var lastRow = CalendarGrid.RowDefinitions.Count - 1;

                if (nextMonthDateIteration.DayOfWeek == DayOfWeek.Sunday) return;

                for (var dayOfWeek = (int) nextMonthDateIteration.DayOfWeek; dayOfWeek < 7; dayOfWeek++)
                {
                    var item = new CalendarItemUserControl(nextMonthDateIteration, "",
                        Application.Current.Resources["CalendarOtherMonthItemBox"] as Style);
                    /*item.PointerEntered += (sender, args) =>
                        {
                            ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarMouseOverItemBox"] as Style;
                        };

                        item.PointerExited += (sender, args) =>
                        {
                            if (((CalendarItemUserControl)sender).Value == this.SelectedDate)
                                ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarSelectedItemBox"] as Style;
                            else
                                ((CalendarItemUserControl)sender).GridStyle = Application.Current.Resources["CalendarOtherMonthItemBox"] as Style;
                        };*/

                    //delegate the tapped event to selection change event
                    /*item.Tapped += (sender, args) =>
                        {
                            //update the selected date value
                            this.SelectedDate = ((CalendarItemUserControl)sender).Value;
                            this.CurrentDate = this.CurrentDate.AddMonths(1);
                            InitializeCalendar();

                            OnSelectionChange(sender, args);
                        };*/

                    item.SetValue(Grid.RowProperty, lastRow);
                    item.SetValue(Grid.ColumnProperty, dayOfWeek);

                    CalendarGrid.Children.Add(item);

                    nextMonthDateIteration = nextMonthDateIteration.AddDays(1);
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void UserControl_Unloaded(object sender, RoutedEventArgs e)
        {
            _meetingService = null;
            Messenger.Default.Unregister(this);
        }
    }
}